#ifndef __TTY_H__
#define __TTY_H__

#include <termios.h>

#define MAX_CONSOLES	8
#define NR_SERIALS		2
#define NR_PTYS			4
#define TTY_BUF_SIZE	1024

extern int NR_CONSOLES;

struct tty_queue {
	unsigned long data;
	unsigned long head;
	unsigned long tail;
	struct task_struct* proc_list;
	char buf[TTY_BUF_SIZE];
};

#define IS_A_CONSOLE(m)		(((m) & 0xc0) == 0x00)
#define IS_A_SERIAL(m)		(((m) & 0xc0) == 0x40)
#define IS_A_PTY(m)			((m) & 0x80)
#define IS_A_PTY_MASTER(m)	(((m) & 0xc0) == 0x80)
#define IS_A_PTY_SLAVE(m)	(((m) & 0xc0) == 0xc0)
#define PTY_OTHER(m)		((m) ^ 0x40)

#define INC(a)	((a) = ((a)+1) & (TTY_BUF_SIZE-1))
#define DEC(a)	((a) = ((a)-1) & (TTY_BUF_SIZE-1))
#define EMPTY(a)	((a)->head == (a)->tail)
#define LEFT(a) 	(((a)->tail - (a)->head - 1) & (TTY_BUF_SIZE - 1))
#define LAST(a)		((a)->buf[(TTY_BUF_SIZE-1) & ((a)->head-1)])
#define FULL(a)		(!LEFT(a))
#define CHARS(a)	(((a)->head - (a)->tail) & (TTY_BUF_SIZE-1))
#define GETCH(queue,c)	(void)({c=(queue)->buf[(queue)->tail]; INC((queue)->tail);})
#define PUTCH(c,queue)	(void)({(queue)->buf[(queue)->head]=c; INC((queue)->head);})

#define EOF_CHAR(tty)	((tty)->termios.c_cc[VEOF])
#define INTR_CHAR(tty)	((tty)->termios.c_cc[VINTR])
#define QUIT_CHAR(tty)	((tty)->termios.c_cc[VQUIT])
#define ERASE_CHAR(tty)	((tty)->termios.c_cc[VERASE])
#define KILL_CHAR(tty)	((tty)->termios.c_cc[VKILL])
#define STOP_CHAR(tty)	((tty)->termios.c_cc[VSTOP])
#define START_CHAR(tty)	((tty)->termios.c_cc[VSTART])
#define SUSPEND_CHAR(tty)	((tty)->termios.c_cc[VSUSP])


struct tty_struct {
	struct termios termios;
	int pgrp;
	int session;
	int stopped;
	void (*write)(struct tty_struct* tty);
	struct tty_queue* read_q;
	struct tty_queue* write_q;
	struct tty_queue* secondary;
};

extern struct tty_struct tty_table[];
extern int fg_console;

#define TTY_TABLE(nr)		\
( tty_table + ( (nr) ? 	\
	(((nr) < 64) ? (nr) - 1 : (nr)) : fg_console ) )

#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\031\0\022\017\027\026\0"

void rs_init(void);
void con_init();
void tty_init();

int tty_read(unsigned c, char* buf, int n);
int tty_write(unsigned c, char* buf, int n);

void con_write(struct tty_struct * tty);
void rs_write(struct tty_struct* tty);
void mpty_write(struct tty_struct* tty);
void spty_write(struct tty_struct* tty);

extern void serial_open(unsigned int line);

void copy_to_cooked(struct tty_struct * tty);

void update_screen(void);

#endif //__TTY_H__